﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Soporte;

namespace Magui
{
    public partial class Lupa : Form
    {
        private Timer _tmrRefresh;

        private IntPtr _hDC_desktop = IntPtr.Zero;
        private IntPtr hDcDesktop
        {
            get
            {
                if (_hDC_desktop == IntPtr.Zero) _hDC_desktop = NativeMethods.GetWindowDC(NativeMethods.GetDesktopWindow());
                return _hDC_desktop;
            }
        }

        private IntPtr _hDC_lupa = IntPtr.Zero;
        private IntPtr hDcLupa
        {
            get
            {
                if (_hDC_lupa == IntPtr.Zero)
                {
                    _hDC_lupa = NativeMethods.CreateCompatibleDC(hDcDesktop);
                    NativeMethods.SelectObject(_hDC_lupa, hBitmap);
                }
                return _hDC_lupa;
            }
        }

        private IntPtr _hBitmap = IntPtr.Zero;
        private IntPtr hBitmap
        {
            get
            {
                if (_hBitmap == IntPtr.Zero)
                {
                    _hBitmap = NativeMethods.CreateCompatibleBitmap(hDcDesktop, this.Width, this.Height);
                }
                return _hBitmap;
            }
        }

        public Lupa()
        {
            InitializeComponent();

            SetLayeredTransparent(this.Handle, this.Location, this.Size);

            // Inicializamos el doble buffer para que no parpadee el formulario
            DoubleBuffered = true;

            this.Paint += new PaintEventHandler(Lupa_Paint);

            _tmrRefresh = new Timer
            {
                Interval = 1000 / 24,
                Enabled = true
            };
            _tmrRefresh.Tick += tmrRefresh_Tick;
        }

        void tmrRefresh_Tick(object sender, EventArgs e)
        {
            Refresh();
        }

        void Lupa_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
                e.Graphics.CompositingQuality = CompositingQuality.HighSpeed;
                e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
                e.Graphics.InterpolationMode = InterpolationMode.Low;
                e.Graphics.DrawImage(CreateImage(2, new Point(), this.Size), 0, 0, this.Width, this.Height);
            }
            catch (Exception ex)
            {
                Console.WriteLine("KO Paint: " + ex.ToString());
            }
        }

        public Image CreateImage(double factor, Point pSource, Size dimension)
        {
            try
            {
                var s = new Size((int)(dimension.Width / factor), (int)(dimension.Height / factor));
                var sc = NativeMethods.TernaryRasterOperations.SRCCOPY;

                NativeMethods.StretchBlt(hDcLupa, 
                                            0, 0, dimension.Width, dimension.Height,
                                         hDcDesktop,
                                            pSource.X, pSource.Y, s.Width, s.Height,
                                         sc);

                return Image.FromHbitmap(hBitmap);
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Sobrecarga MaGUI: " + ex.ToString()); 
                Console.WriteLine("KO: " + ex.ToString());
            }

            return null;
        }

        /// <summary>
        /// El sistema operativo ha de ser capaz de obviar la existencia del formulario
        /// y siga creando y renderizando, al completo, la imagen que queda debajo
        /// es decir; trabaja con un elemento opaco pero a la hora de pintar objetos
        /// hace como si fuera transparente
        /// </summary>
        public void SetLayeredTransparent(IntPtr handle, Point p, Size s)
        {
            if (
                NativeMethods.SetWindowLong(handle, NativeMethods.GWL_EXSTYLE,
                                            NativeMethods.WS_EX_LAYERED | NativeMethods.WS_EX_TRANSPARENT |
                                            NativeMethods.WS_EX_TOPMOST) == 0)
                throw new Win32Exception();

            if (NativeMethods.SetLayeredWindowAttributes(handle, 0, 255, NativeMethods.LWA_ALPHA) == 0)
                throw new Win32Exception();

            //Asignamos la propiedad TOPMOST para poner la lupa sobre los elementos de tipo toolTip,...
            NativeMethods.SetWindowPos(handle, NativeMethods.HWND_TOPMOST,
                                       p.X, p.Y, s.Width, s.Height, NativeMethods.SWP_NOACTIVATE);

        }
    }
}
